其實這好像才是昨天的主題,但是我好像太急著要說坑的部分,所以就忘了先仔細介紹我專案的架構
當然,我還沒有完全移除 example的部分,也就是我下載回來改的 Redux & Material UI 的 Template
但是我已經有先把架構都列出來了 給大家參考看看
先附上範例他原本的 src資料夾架構
然後是我整理之後的
我們一一來介紹一下放了什麼東西
component.jsx的長相
index.js的長相
最後 像我如果要用這一個component的話
就只要 import LoginPage_CP from '../../components/LoginPage'
containers
簡單說 containers 裡面就是存放跟Redux很有關聯的東西,就我的理解是這樣的
Component 如果你想要去更新 或讀取state 就是要有人把你連起來 其實這概念跟 AngularJs & Angular2 的service 監視動作很像.
所以,container就是一個大的組合器 她把Redux Action Store Component 集合起來 最後讓你的component 讀取state 操作state 更甚至是你要去跟後端要東西 都可以幫你整個綁起來,當然囉,最後你在頁面要import 近來render成畫面的 也會是container 不會是component
先放張圖看看樣子 我們會再開一篇仔細說怎麼串的
再來是一些比較像資源的東西,像是
fonts -> 首頁要用到的資源,但是font-awesome 我有把它換成react的了,沒啥坑,裝一裝就可以用,自己google
images -> 放圖片,一個小地方要注意,如果你是在 render return裡面的話,
記得要 <img src={require('相對路徑')} />
重點來了 以我的經驗,寫專案沒有這麼完美,你可能會用到一些例外,例如這一部分
有些圖片,他偏偏就是在一些設定裡面要先給他,並不是寫在 render return
這時候我是這樣解決的
require('../../images/General/left_arrow.png')
require('../../images/General/right_arrow.png')
const options = {
items: 3,
loop: true,
margin: 20,
nav: true,
dots: true,
smartSpeed: 800,
autoHeight: true,
navText: [
"<div class='owl-direction'><img src='./left_arrow.png' /></FontAwesomeIcon></div>",
"<div class='owl-direction'><img src='./right_arrow.png' /></FontAwesomeIcon></div>",
],
responsive:{
0: {
items:1
},
600:{
items:2
},
1000:{
items:3
}
}
};
這邊我載入的圖片,是用來給 react-owl-carousel2 作為左右的箭頭的
/redux/actions 放你的方法 看你是要createAction fetch 還是 dispatch 給 reducer 讓他去改狀態,都會寫在這裡
/redux/constants 主要我放model.js 還有 actionTypes.js 你把這裡想成 龜襪你的state tree 要長什麼樣子 還有什麼方法可以改變 state tree
/redux/reducers 簡而言之 剛剛我們說的action那邊會發一個dispatch出來 然後對應到了 reducer這邊後 他就會去對state tree 裡面做修改等的動作,我是有看到有人會再reducer裡面坐除了改state的事情,但是我覺得那樣會很亂,因為每種事情每個地方都有做的話,你以後Debug會滿辛苦的
/redux/stores 最後是store,這裏也沒什麼好說的,不過就是你如果有設定非同步的動作的話,這裡就要做設定
這是我configureStore.jsx的內容
Immutable 一個不會互相污染的東西
reduxThunk 非同步
rootReducer 我把我所有的reducer包在一包,一起送過來
其他自己 google or copy paste
import {createStore, applyMiddleware} from 'redux';
import { createLogger} from 'redux-logger';
import Immutable from 'immutable';
import reduxThunk from 'redux-thunk';
import rootReducer from '../reducers';
const initialState = Immutable.Map();
export default createStore(
rootReducer,
initialState,
applyMiddleware(reduxThunk, createLogger({stateTransformer: state => state.toJS() }))
基本上專案架構就是這樣,我們來看看進入點吧
你如果有去下載一些 HTML5 的範本下來 他的 index.html 應該都會有滿多 css & script 載入 像是jquery bootstrap~
但是,那個最後你要 npm run build 就會一起死給你看
所以記得喔 該搬的要搬一搬 該用npm裝得要裝一裝 大部分會有的問題 就是我上一篇提到的 jquery loading
或是 image 的使用方式,其他應該都是一般 Google 就會有了
這就是我改完之後的 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, height=device-height, minimum-scale=1.0, initial-scale=1.0, user-scalable=0">
<meta name="description" content="SuccMail">
<title>Simple is Best | SuccMail</title>
<!-- Facebook and Twitter integration -->
<meta property="og:title" content=""/>
<meta property="og:image" content=""/>
<meta property="og:url" content=""/>
<meta property="og:site_name" content=""/>
<meta property="og:description" content=""/>
<meta name="twitter:title" content="" />
<meta name="twitter:image" content="" />
<meta name="twitter:url" content="" />
<meta name="twitter:card" content="" />
</head>
<body>
<div id="app"></div>
<!-- Roboto font -->
<script>
var WebFontConfig = {
google: { families: [ 'Roboto:400,300,500:latin' ] }
};
(function() {
var wf = document.createElement('script');
wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
wf.type = 'text/javascript';
wf.async = 'true';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(wf, s);
})();
</script>
<!-- Delay Loading -->
</body>
</html>
最後附上 package.json 應該就可以正式的完成到可以動的專案了
{
"name": "succmail",
"version": "0.0.1",
"description": "YungYuLin succmail",
"engines": {
"npm": ">=3"
},
"scripts": {
"start": "npm-run-all --parallel test:watch open:src lint:watch",
"open:src": "babel-node tools/srcServer.js",
"open:dist": "babel-node tools/distServer.js",
"lint": "esw webpack.config.* src tools --color",
"lint:watch": "npm run lint -- --watch",
"clean-dist": "npm run remove-dist && mkdir dist",
"remove-dist": "rimraf ./dist",
"prebuild": "npm run clean-dist && npm run lint && npm run test",
"build": "babel-node tools/build.js && npm run open:dist",
"test": "mocha tools/testSetup.js \"src/**/*.spec.js\" --reporter progress",
"test:cover": "babel-node node_modules/isparta/bin/isparta cover --root src --report html node_modules/mocha/bin/_mocha -- --require ./tools/testSetup.js \"src/**/*.spec.js\" --reporter progress",
"test:cover:travis": "babel-node node_modules/isparta/bin/isparta cover --root src --report lcovonly _mocha -- --require ./tools/testSetup.js \"src/**/*.spec.js\" && cat ./coverage/lcov.info | node_modules/coveralls/bin/coveralls.js",
"test:watch": "npm run test -- --watch",
"open:cover": "npm run test:cover && open coverage/index.html"
},
"author": "Yung-Yu-Lin",
"license": "SuccMail",
"dependencies": {
"@fortawesome/fontawesome": "1.0.1",
"@fortawesome/fontawesome-free-brands": "5.0.1",
"@fortawesome/fontawesome-free-solid": "5.0.1",
"@fortawesome/react-fontawesome": "0.0.16",
"bundle-loader": "0.5.5",
"expose-loader": "0.7.4",
"flexboxgrid": "6.3.1",
"font-awesome": "4.7.0",
"history": "4.5.1",
"i18next": "10.2.1",
"i18next-browser-languagedetector": "2.1.0",
"i18next-xhr-backend": "1.5.0",
"immutable": "3.8.2",
"jquery": "2.1.4",
"material-ui": "0.17.0",
"react": "15.4.2",
"react-dom": "15.4.2",
"react-i18next": "7.1.1",
"react-owl-carousel2": "0.2.1",
"react-redux": "5.0.6",
"react-router": "3.0.2",
"react-tap-event-plugin": "2.0.1",
"recharts": "0.20.8",
"redux": "3.7.2",
"redux-actions": "2.2.1",
"redux-immutable": "4.0.0",
"redux-thunk": "2.2.0",
"whatwg-fetch": "2.0.3"
},
"devDependencies": {
"autoprefixer": "6.7.3",
"babel-cli": "6.23.0",
"babel-core": "6.23.1",
"babel-eslint": "8.0.3",
"babel-loader": "6.3.2",
"babel-plugin-react-display-name": "2.0.0",
"babel-plugin-transform-react-constant-elements": "6.23.0",
"babel-plugin-transform-react-remove-prop-types": "0.3.2",
"babel-preset-es2015": "6.22.0",
"babel-preset-react": "6.23.0",
"babel-preset-react-hmre": "1.1.1",
"babel-preset-stage-1": "6.22.0",
"babel-register": "6.23.0",
"browser-sync": "2.18.8",
"chai": "3.5.0",
"chalk": "1.1.3",
"connect-history-api-fallback": "1.3.0",
"coveralls": "2.11.16",
"cross-env": "3.1.4",
"css-loader": "0.26.1",
"enzyme": "2.7.1",
"eslint": "3.15.0",
"eslint-config-airbnb": "16.1.0",
"eslint-loader": "1.9.0",
"eslint-plugin-import": "2.2.0",
"eslint-plugin-jsx-a11y": "4.0.0",
"eslint-plugin-react": "6.10.0",
"eslint-watch": "3.0.0",
"extract-text-webpack-plugin": "1.0.1",
"file-loader": "0.10.0",
"html-webpack-plugin": "2.22.0",
"isparta": "4.0.0",
"json-loader": "0.5.7",
"mocha": "3.2.0",
"node-sass": "4.5.0",
"npm-run-all": "4.0.1",
"open": "0.0.5",
"postcss-loader": "1.3.1",
"prompt": "1.0.0",
"react-addons-test-utils": "15.4.2",
"redux-immutable-state-invariant": "1.2.4",
"redux-logger": "3.0.6",
"replace": "0.3.0",
"rimraf": "2.5.4",
"sass-loader": "6.0.1",
"script-loader": "0.7.2",
"sinon": "1.17.7",
"sinon-chai": "2.8.0",
"style-loader": "0.13.1",
"url-loader": "0.5.7",
"webpack": "1.13.1",
"webpack-dev-middleware": "1.6.1",
"webpack-hot-middleware": "2.12.2",
"webpack-md5-hash": "0.0.5"
},
"keywords": [
"SuccMail"
]
}
對了,突然想起,我曾經在安裝某個套件的時候 webpack 一直該該叫 最後我就把版本指定在 1.13.1
以前在寫Angular2 也是這樣~ 那今天就先到這裡囉 希望你也可以省時省力的把外面的範例
改成你想要的樣子 節省你的時間 還有 公司的成本